#pragma once

#include "stdafx.h"
#include "util/concurrent.h"

namespace natrium {
	namespace core {
		/* 
		 * Threaded logger; should be pretty high performance. Syntactically behaves almost like a std stream, only automatically adds a newline after each use.
		 */
		class Logger:
			public boost::noncopyable
		{
		private:
			struct LogHelper;

		public:
			friend struct LogHelper;

			Logger(const std::string& filename);
			virtual ~Logger();
		
			template <typename T>
			LogHelper operator << (const T& data) {
				LogHelper lh(this);
				lh << data;
				return lh;
			}

			LogHelper operator << (std::ostream& (*fn)(std::ostream& os)); //overloading this allows stream functions to operate on a Logger (such as std::endl)

			LogHelper debug();
			LogHelper info();
			LogHelper warning();
			LogHelper error();
			LogHelper fatal();

		private:
			void flush(const std::string& message);

			//Helper struct, accumulates the message and flushes it when it goes out of scope
			struct LogHelper {
				LogHelper(Logger* owner);
				LogHelper(LogHelper&& lh);
				~LogHelper();

				template <typename T>
				LogHelper& operator << (const T& data) {
					mBuffer << data;
					return *this;
				}

				LogHelper& operator << (std::ostream& (*fn)(std::ostream& os));

				std::ostringstream mBuffer;
				Logger* mOwner;
			};

			struct Output {
				Output(const std::string& filename);

				std::ofstream mOutputFile;
				std::ostream& mCout;
			};

			bool mDone;
			std::vector<std::thread> mThread;
			util::ConcurrentQueue<std::function<void()>> mBacklog;

			Output mOutput;
		};
	}
}

extern natrium::core::Logger gLog;
